﻿#include "OiPCH.hpp"
#include <QGraphicsScene>
#include <QtCharts/QValueAxis>
#include "View/OiScene.hpp"

using namespace QtCharts;
QList<double> g_VDefinitionPoint;
QList<double> g_VFormualPoint;
int g_precision = 0;
namespace Oi
{
    namespace PLScannerCore
    {
        QPainterPath arrowPath(const QPointF& p1, const QPointF& p2, int direct /*= 0*/, int endIndex /*= 0*/, int arrowSize /*= 10*/)
        {
            QPainterPath path;

            QLineF line(p1, p2);

            double angle = ::acos(line.dx() / line.length());
            if(line.dy() >= 0)
                angle = ( M_PI * 2 ) - angle;

            if(endIndex == 0 || endIndex == 1)
            {
                if(direct == 0)
                {
                    QPointF arrowP1 = p1 + QPointF(sin(angle + M_PI / 3) * arrowSize,
                        cos(angle + M_PI / 3) * arrowSize);
                    QPointF arrowP2 = p1 + QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize,
                        cos(angle + M_PI - M_PI / 3) * arrowSize);

                    path.moveTo(p1);
                    path.lineTo(arrowP1);
                    path.lineTo(arrowP2);
                    path.lineTo(p1);
                }
                else
                {
                    QPointF arrowP1 = p1 - QPointF(sin(angle + M_PI / 3) * arrowSize,
                        cos(angle + M_PI / 3) * arrowSize);
                    QPointF arrowP2 = p1 - QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize,
                        cos(angle + M_PI - M_PI / 3) * arrowSize);
                    QPointF extendP1 = p1 - QPointF(sin(angle) * 2 * arrowSize,
                        cos(angle) * 2 * arrowSize);

                    path.moveTo(p1);
                    path.lineTo(arrowP1);
                    path.lineTo(arrowP2);
                    path.lineTo(p1);
                    path.lineTo(extendP1);
                }
            }

            if(endIndex == 0 || endIndex == 2)
            {
                if(direct == 0)
                {
                    QPointF arrowP1 = p2 - QPointF(sin(angle + M_PI / 3) * arrowSize,
                        cos(angle + M_PI / 3) * arrowSize);
                    QPointF arrowP2 = p2 - QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize,
                        cos(angle + M_PI - M_PI / 3) * arrowSize);

                    path.moveTo(p2);
                    path.lineTo(arrowP1);
                    path.lineTo(arrowP2);
                    path.lineTo(p2);
                }
                else
                {
                    QPointF arrowP1 = p2 + QPointF(sin(angle + M_PI / 3) * arrowSize,
                        cos(angle + M_PI / 3) * arrowSize);
                    QPointF arrowP2 = p2 + QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize,
                        cos(angle + M_PI - M_PI / 3) * arrowSize);
                    QPointF extendP2 = p2 + QPointF(sin(angle) * 2 * arrowSize,
                        cos(angle) * 2 * arrowSize);

                    path.moveTo(p2);
                    path.lineTo(arrowP1);
                    path.lineTo(arrowP2);
                    path.lineTo(p2);
                    path.lineTo(extendP2);
                }
            }

            return path;
        }

        class DefinitionPointTool : public QGraphicsItem
        {
        public:
            DefinitionPointTool(QGraphicsItem *parent = nullptr) :QGraphicsItem(parent)
            {
            }

            void change();

            virtual QRectF textRect() const = 0;
        };

        void DefinitionPointTool::change()
        {
            prepareGeometryChange();
            update();
        }

        class VDefinitionPoint : public DefinitionPointTool
        {
        public:
            VDefinitionPoint(QGraphicsItem *parent = nullptr) :DefinitionPointTool(parent)
            {
            }

            QRectF boundingRect() const;

            QRectF textRect() const;

            void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR);

        public:
            QPointF definitionPoint;

            QRectF displayRect;

            QTransform transform;
        };

        class HDefinitionPoint : public DefinitionPointTool
        {
        public:
            HDefinitionPoint(QGraphicsItem *parent = nullptr) :DefinitionPointTool(parent)
            {

            }

            QRectF boundingRect() const;

            QRectF textRect() const;

            void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR);

        public:
            QPointF definitionPoint;

            QPointF cornerPoint;

            QRectF displayRect;

            QTransform transform;
        };

        class WDefinitionPoint : public DefinitionPointTool
        {
        public:
            WDefinitionPoint(QGraphicsItem *parent = nullptr) :DefinitionPointTool(parent)
            {

            }

            QRectF boundingRect() const;

            QRectF textRect() const;

            void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR);

        public:
            QPointF definitionPoint1;

            QPointF definitionPoint2;

            QRectF displayRect;
        };

        class InfoBox : public QGraphicsItem
        {
        public:
            InfoBox(QGraphicsItem *parent = nullptr) :QGraphicsItem(parent)
            {

            }

            QRectF boundingRect() const;

            void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR);

        public:
            double stdValue = 0.0;
            double measureValue = 0.0;
            //QPointF _referPoint;
        public:
            QGraphicsView* _view;
        };


        QRectF VDefinitionPoint::boundingRect() const
        {
            QPointF p2 = QPointF(definitionPoint.x(), 0);

            return QRectF(definitionPoint + QPointF(-10.0, +0.0), p2 + QPointF(+10.0, -1.0));
        }

        QRectF VDefinitionPoint::textRect() const
        {
            return displayRect;
        }

        void VDefinitionPoint::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget /*= Q_NULLPTR*/)
        {
            transform = painter->transform();
            auto cf = painter->font();
            cf.setPointSize(20);

            painter->save();

            painter->scale(1.0 / transform.m11(), 1.0 / transform.m22());

//             painter->setPen(QPen(Qt::gray, 1, Qt::DashDotDotLine));
// 
//             auto tl = boundingRect().topLeft();
//             auto br = boundingRect().bottomRight();
//             painter->drawRect(QRectF(QPointF(tl.x() * transform.m11(), tl.y() * transform.m22()), QPointF(br.x() * transform.m11(), br.y() * transform.m22())));

            painter->setPen(QPen(Qt::darkYellow, 1));

            QPointF p1(definitionPoint.x() * transform.m11(), definitionPoint.y() * transform.m22());
            QPointF p2(definitionPoint.x() * transform.m11(), 0);

            if (fabs(definitionPoint.y() * transform.m22()) > 40.0)
            {
                painter->fillPath(arrowPath(p1,  p2, 0, 0, 10) ,Qt::darkYellow);
            }
            else
            {
                painter->fillPath(arrowPath(p1,  p2, 1, 0, 10) ,Qt::darkYellow);
            }
            painter->drawLine(p1, p2);

            painter->setFont(cf);

            QString text = QString::number(fabs(definitionPoint.y()), 'f', g_precision);
            QFontMetrics fm(cf);
            auto th = fm.height();
            auto tw = fm.width(text);
            auto ttl = p2 + QPointF(-tw / 2, th + 2);
            painter->save();
//            painter->drawText(ttl, QString::number(definitionPoint.y()));
            QString strText = "";
            int index = 0;
            for (int i = 0; i < g_VDefinitionPoint.size();i++)
            {
                if (g_VDefinitionPoint[i] == definitionPoint.x())
                {
                    strText = QString("T%1").arg(i+1) + QString("(") + QString::number(definitionPoint.y(), 'f', g_precision) + QString(")");
                    index = i + 1;
                    break;
                }
            }
            if (strText != "")
            {
                painter->translate(ttl.x(), ttl.y());
                painter->rotate(90);
                painter->drawText(QPointF(0.0, 0.0), strText);
                
            }
//            else
//            {
//                for (int i = 0; i < g_VFormualPoint.size(); i++)
//                {
//                    if (g_VFormualPoint[i] == definitionPoint.x())
//                    {
//                        strText = QString("T%1").arg(i + 1) + QString("(") + QString::number(definitionPoint.y(), 'f', g_precision) + QString(")");
//                    }
//                }
////                painter->rotate(90);
//                if (strText != "")
//                {
//                    painter->drawText(ttl, strText);
//                }
//                else
//                {
//                    painter->drawText(ttl, QString::number(definitionPoint.y()));
//                }
//            }
//            displayRect = QRectF(QPointF(ttl.x() / transform.m11(), ttl.y() / transform.m22()), QSizeF(1.0 * tw / transform.m11(), fabs(1.0 *  th / transform.m22())));

            painter->restore();
        }
        
        QRectF HDefinitionPoint::boundingRect() const
        {
            return QRectF(qMin(0.0, cornerPoint.x()), cornerPoint.y() - 1.0, fabs(cornerPoint.x()), +2.0);
        }

        QRectF HDefinitionPoint::textRect() const
        {
            return displayRect;
        }

        void HDefinitionPoint::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget /*= Q_NULLPTR*/)
        {
            transform = painter->transform();
            auto cf = painter->font();
            cf.setPointSize(12);

            painter->save();

            painter->scale(1.0 / transform.m11(), 1.0 / transform.m22());

//             painter->setPen(QPen(Qt::gray, 1, Qt::DashDotDotLine));
// 
//             auto tl = boundingRect().topLeft();
//             auto br = boundingRect().bottomRight();
//             painter->drawRect(QRectF(QPointF(tl.x() * transform.m11(), tl.y() * transform.m22()), QPointF(br.x() * transform.m11(), br.y() * transform.m22())));


            painter->setPen(QPen(Qt::darkYellow, 1));

            QPointF p1(definitionPoint.x() * transform.m11(), definitionPoint.y() * transform.m22());
            QPointF p2(0, cornerPoint.y() * transform.m22());
            QPointF p3(definitionPoint.x() * transform.m11(), cornerPoint.y() * transform.m22());
            QPointF p4(definitionPoint.x() * transform.m11(), cornerPoint.y() * transform.m22() - 5);

            if(fabs(definitionPoint.x() * transform.m11()) > 40.0)
            {
                painter->fillPath(arrowPath(p2, p3, 0, 0, 10), Qt::darkYellow);
            }
            else
            {
                painter->fillPath(arrowPath(p2, p3, 1, 0, 10), Qt::darkYellow);
            }
            painter->drawLine(p2, p3);
            painter->drawLine(p1, p4);

            painter->setFont(cf);
            QString text = QString::number(fabs(definitionPoint.x()));

            QFontMetrics fm(cf);
            auto tw = fm.width(text);
            auto th = fm.height();
            auto ttl = (p2 + p3) / 2 - QPointF(tw / 2, 0);

            painter->drawText(ttl, text);

            displayRect = QRectF(QPointF(ttl.x() / transform.m11(), ttl.y() / transform.m22()), QSizeF(1.0 * tw / transform.m11(), fabs(1.0 *  th / transform.m22())));

            painter->restore();
        }

        QRectF WDefinitionPoint::boundingRect() const
        {
            return QRectF(definitionPoint1 + QPointF(0, -1.0), definitionPoint2 + QPointF(0, +1.0));
        }

        QRectF WDefinitionPoint::textRect() const
        {
            return displayRect;
        }

        void WDefinitionPoint::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget /*= Q_NULLPTR*/)
        {
            auto transform = painter->transform();
            auto cf = painter->font();
            cf.setPointSize(12);

            painter->save();

            painter->scale(1.0 / transform.m11(), 1.0 / transform.m22());

            painter->setPen(QPen(Qt::darkYellow, 1));

            QPointF p1(definitionPoint1.x() * transform.m11(), 0);
            QPointF p2(definitionPoint2.x() * transform.m11(), 0);
            
            painter->fillPath(arrowPath(p1, p2, 0, 0, 10), Qt::darkYellow);
            painter->drawLine(p1, p2);

            painter->setFont(cf);
            QString text = QString::number(fabs(definitionPoint1.x() - definitionPoint2.x()), 'f', 2);

            QFontMetrics fm(cf);
            auto tw = fm.width(text);
            auto th = fm.height();
            auto ttl = (p1 + p2) / 2 - QPointF(tw / 2, 0);

            painter->drawText(ttl, text);

            displayRect = QRectF(QPointF(ttl.x() / transform.m11(), ttl.y() / transform.m22()), QSizeF(1.0 * tw / transform.m11(), fabs(1.0 *  th / transform.m22())));

            painter->restore();
        }

        QRectF InfoBox::boundingRect() const
        {
            auto tf = _view->transform();
            auto rect = QRectF(0, 0, 120.0 / tf.m11(), 80.0 / tf.m22());
            return rect;
        }

        void InfoBox::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget /*= Q_NULLPTR*/)
        {
            //auto rp = mapFromScene(_referPoint);
            auto vr = _view->rect();
            auto sp1 = mapFromScene(_view->mapToScene(vr.topLeft()));
            auto sp2 = mapFromScene(_view->mapToScene(vr.bottomRight()));
            auto left = qMin(sp1.x(), sp2.x());
            auto right = qMax(sp1.x(), sp2.x());
            auto top = qMin(sp1.y(), sp2.y());
            auto bottom = qMax(sp1.y(), sp2.y());

            auto transform = painter->transform();
            auto cf = painter->font();
            cf.setPointSize(8);

            painter->save();
            painter->scale(1.0 / transform.m11(), 1.0 / transform.m22());

            painter->setPen(Qt::NoPen);
            painter->setBrush(QColor(255, 255, 255, 100));

            if (measureValue > 0.0)
            {
                painter->drawRect(QRectF(0, 0, 120.0, 80.0 ));
            }
            else
            {
                painter->drawRect(QRectF(0, 0, 120.0, 30.0));
            }

            painter->setPen(QPen(Qt::gray, 1.0, Qt::DashDotDotLine));
            painter->drawLine(QPointF(-10.0, 0.0), QPointF(left * transform.m11(), 0.0));
            painter->drawLine(QPointF(+10.0, 0.0), QPointF(right * transform.m11(), 0.0));
            painter->drawLine(QPointF(0.0, -10.0), QPointF(0.0, bottom * transform.m22()));
            painter->drawLine(QPointF(0.0, +10.0), QPointF(0.0, top * transform.m22()));

            painter->setFont(cf);
            painter->setPen(Qt::black);

            QFontMetrics fm(cf);
            auto th = fm.height();
            double height = fm.height() +1.0;

            QString text1 = QObject::tr("标准值:") + QString::number(fabs(stdValue), 'f', 2);
            painter->drawText(QPointF(20.0, height), text1);
            height += (fm.height() + 3);

            if (measureValue > 0.0)
            {
                QString text2 = QObject::tr("测量值:") + QString::number(fabs(measureValue), 'f', 2);
                QString text3 = QObject::tr("误差值:") + QString::number(fabs(stdValue - measureValue), 'f', 2);
                painter->drawText(QPointF(20.0, height), text2);
                height += (fm.height() + 3);
                painter->drawText(QPointF(20.0, height), text3);
            }
            

//             QFontMetrics fm(cf);
//             auto tw = fm.width(text);
//             auto th = fm.height();
//             auto ttl = (p2 + p3) / 2 - QPointF(tw / 2, 0);
// 
//             painter->drawText(ttl, text);
// 
//             displayRect = QRectF(QPointF(ttl.x() / transform.m11(), ttl.y() / transform.m22()), QSizeF(1.0 * tw / transform.m11(), fabs(1.0 *  th / transform.m22())));

            painter->restore();
        }

        class ToolProfilesItem : public QGraphicsItem
        {
        public:
            ToolProfilesItem(QGraphicsItem *parent = nullptr) :QGraphicsItem(parent)
            {
            }

            QRectF boundingRect() const;

            void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR);

        public:
            QList<QList<QPointF>> _profiles;

            QList<QList<QPointF>> _template;
        };

        QRectF ToolProfilesItem::boundingRect() const
        {
            QRectF rect;

            for (auto profile : _template)
            {
                auto pR = QPolygonF(profile.toVector()).boundingRect();
                if (rect.isEmpty())
                {
                    rect = pR;
                }
                else
                {
                    rect |= pR;
                }
            }

            for(auto profile : _profiles)
            {
                auto pR = QPolygonF(profile.toVector()).boundingRect();
                if(rect.isEmpty())
                {
                    rect = pR;
                }
                else
                {
                    rect |= pR;
                }
            }

            return rect.normalized().adjusted(-0.1, -0.1, 0.1, 0.1);
        }

        void ToolProfilesItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget /*= Q_NULLPTR*/)
        {
            auto transform = painter->transform();

            painter->save();

            painter->scale(1.0 / transform.m11(), 1.0 / transform.m22());

//             painter->setPen(QPen(Qt::gray, 1, Qt::DashDotDotLine));
// 
//             auto tl = boundingRect().topLeft();
//             auto br = boundingRect().bottomRight();
//             painter->drawRect(QRectF(QPointF(tl.x() * transform.m11(), tl.y() * transform.m22()), QPointF(br.x() * transform.m11(), br.y() * transform.m22())));
            
            for(auto profile : _template)
            {
                painter->setPen(QPen(Qt::darkBlue, 2));

                for(auto& p : profile)
                {
                    p.setX(p.x() * transform.m11());
                    p.setY(p.y() * transform.m22());
                }

                painter->drawPolyline(profile.toVector().data(), profile.size());

                if (profile.size() >= 2)
                {
                    painter->setPen(QPen(Qt::darkBlue, 2, Qt::DashDotDotLine));
                    painter->drawLine(QLineF(profile.front(), profile.back()));
                }

                painter->setPen(QPen(Qt::darkYellow, 4));

                painter->drawPoints(profile.toVector());
            }

            for (auto profile : _profiles)
            {
                if (profile.size() > 0)
                {
                    painter->setPen(QPen(Qt::green, 2));

                    for (auto& p : profile)
                    {
                        p.setX(p.x() * transform.m11());
                        p.setY(p.y() * transform.m22());
                    }

                    painter->drawPolyline(profile.toVector().data(), profile.size());
                }
               

//                 if (profile.size() >= 2)
//                 {
//                     painter->setPen(QPen(Qt::black, 2, Qt::DashDotDotLine));
//                     painter->drawLine(QLineF(profile.front(), profile.back()));
//                 }

//                 painter->setPen(QPen(Qt::black, 4));
// 
//                 painter->drawPoints(profile.toVector());
            }
           
            painter->restore();
        }

        class ToolProfilesViewImpl : public Impl<ToolProfilesView>
        {
        public:
            void init();

        public:
            void clearView();
            void relocate(bool zoom = true);
            double y_at_x(double x) const;
            void updatePageFlag();

        public:
            ToolProfilesItem* _line;
            QMap<int, VDefinitionPoint*> _vps;
            QMap<int, HDefinitionPoint*> _hps;

            QList<VDefinitionPoint*> _mvps;
            QList<HDefinitionPoint*> _mhps;

            VDefinitionPoint* _fmvp = nullptr;
            HDefinitionPoint* _fmhp = nullptr;

            WDefinitionPoint* _wps = nullptr;

            InfoBox* _info;

        public:
            ProductParams _params;

        public:
            View::Scene* _scene;

        public:
            bool _addToolMode;
            bool _editable;

            int _pageFlag;
        };

        void ToolProfilesViewImpl::init()
        {
            OI_Q(ToolProfilesView);

            _addToolMode = false;
            _pageFlag = PMP_ALL;
            g_precision = Core::OiSettings()->value("Measure/precision", 2).toInt();
            q->setRenderHints(q->renderHints() | QPainter::Antialiasing);
            q->setDragMode(QGraphicsView::RubberBandDrag);
            q->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
            q->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
            q->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
            q->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
            q->setMouseTracking(true);
            q->setFrameShape(QFrame::NoFrame);
            q->setAttribute(Qt::WA_MacNormalSize);

            _scene = new View::Scene(q);
            q->setScene(_scene);

            _line = new ToolProfilesItem();
            _scene->addItem(_line);
            _line->setZValue(1);
            _scene->setBackgroundBrush(PLScannerStyle::ChartBgColor());

            _scene->setSceneRect(1.0 * INT_MIN, 1.0 * INT_MIN, 2.0 * INT_MAX, 2.0 * INT_MAX);

            auto transform = q->transform();
            transform.rotate(180.0, Qt::XAxis);
            q->setTransform(transform);

            _info = new InfoBox();
            _info->_view = q;
            _scene->addItem(_info);

           
            q->setMouseTracking(true);
            q->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
            q->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
            q->setContextMenuPolicy(Qt::DefaultContextMenu);
            q->setCursor(Qt::ArrowCursor);
        }

        void ToolProfilesViewImpl::clearView()
        {
            OI_Q(ToolProfilesView);
            
        }

        void ToolProfilesViewImpl::relocate(bool zoom)
        {
            OI_Q(ToolProfilesView);
            auto lb = _line->boundingRect();
            int block = 0;

            auto dr = q->rect();

            double yratio = 1.0 * dr.height() / lb.height();

            //auto tf = q->transform();

            auto list = _hps.values();

            if (_pageFlag & PMP_ThicknessMeasure)
            {
                list.append(_mhps);
            }
            
            if (_pageFlag & PMP_FixedMeasure)
            {
                if (_fmhp)
                {
                    list.append(_fmhp);
                }
            }

            std::sort(list.begin(), list.end(), [](HDefinitionPoint* p1, HDefinitionPoint* p2) { return fabs(p1->definitionPoint.x()) < fabs(p2->definitionPoint.x()); });

            double preLen = -1;
            for(auto& hp : list)
            {
                if (zoom)
                {
                    if(fabs(hp->definitionPoint.x()) != preLen)
                    {
                        hp->cornerPoint = QPointF(hp->definitionPoint.x(), lb.bottom() + 100.0 * ( ++block ) / yratio);
                    }
                    else
                    {
                        hp->cornerPoint = QPointF(hp->definitionPoint.x(), lb.bottom() + 100.0 * ( block ) / yratio);
                    }
                }
                else
                {
                    if(fabs(hp->definitionPoint.x()) != preLen)
                    {
                        hp->cornerPoint = QPointF(hp->definitionPoint.x(), lb.bottom() + 2.0 * ( ++block ));
                    }
                    else
                    {
                        hp->cornerPoint = QPointF(hp->definitionPoint.x(), lb.bottom() + 2.0 * ( block ));
                    }
                }

                preLen = fabs(hp->definitionPoint.x());
            }
        }

        double ToolProfilesViewImpl::y_at_x(double x) const
        {
            if (_line->_profiles.size() > 0)
            {
                return PLScannerUtil::y_at_profile(_line->_profiles[0], x);
            }
            else if(_line->_template.size() > 0)
            {
                return PLScannerUtil::y_at_profile(_line->_template[0], x);
            }
            else
            {
                return -1;
            }
        }

        void ToolProfilesViewImpl::updatePageFlag()
        {

            if (_pageFlag & PMP_ThicknessMeasure)
            {
                for (auto hps : _mhps)
                {
                    hps->show();
                }

                for (auto vps : _mvps)
                {
                    vps->show();
                }
            }
            else
            {
                for (auto hps : _mhps)
                {
                    hps->hide();
                }

                for (auto vps : _mvps)
                {
                    vps->hide();
                }
            }

            if (_pageFlag & PMP_FixedMeasure)
            {
                if (_fmhp && _fmvp)
                {
                    _fmhp->show();
                    _fmvp->show();
                }
            }
            else
            {
                if (_fmhp && _fmvp)
                {
                    _fmhp->hide();
                    _fmvp->hide();
                }
            }

            if (!(PLScanner::instance()->profileDispalyOption & MT_DefinitionThickness))
            {
                for (auto hps : _hps)
                {
                    hps->hide();
                }

                for (auto vps : _vps)
                {
                    vps->hide();
                }
            }

            if (!(PLScanner::instance()->profileDispalyOption & MT_TotolWidth))
            {
                if (_wps)
                {
                    _wps->hide();
                }
            }

            if (!(PLScanner::instance()->profileDispalyOption & MT_MeasureThickness))
            {
                for (auto hps : _mhps)
                {
                    hps->hide();
                }

                for (auto vps : _mvps)
                {
                    vps->hide();
                }
            }
        }

        ToolProfilesView::ToolProfilesView(QWidget * parent /*= nullptr*/)
            : QGraphicsView(parent)
        {
            OI_I(ToolProfilesView)->init();

        }

        void ToolProfilesView::setPageFlag(ProductMeasurePage flag)
        {
            OI_F(ToolProfilesView);
            d->_pageFlag = flag;
            d->updatePageFlag();
        }

        void ToolProfilesView::setParams(const ProductParams& params)
        {
            OI_F(ToolProfilesView);

            onClearView();

            setTemplate(params.profiles);

            setProfiles(OiProfiles());

            for (auto& vp : d->_vps)
            {
                delete vp;
            }

            d->_params = params;
            
            d->_vps.clear();

            for(auto& hp : d->_hps)
            {
                delete hp;
            }

            d->_hps.clear();

            for (auto& hp : d->_mhps)
            {
                delete hp;
            }

            d->_mhps.clear();

            for (auto& vp : d->_mvps)
            {
                delete vp;
            }

            d->_mvps.clear();

            if (!d->_wps)
            {
                d->_wps = new WDefinitionPoint();
                d->_scene->addItem(d->_wps);
                d->_wps->setZValue(100);
            }

            if (d->_wps)
            {
                d->_wps->definitionPoint1 = QPointF(-0.5 * params.materialsWidth, 0);
                d->_wps->definitionPoint2 = QPointF(+0.5 * params.materialsWidth, 0);
            }

            if (!d->_fmhp)
            {
                d -> _fmhp = new HDefinitionPoint();
                d->_scene->addItem(d->_fmhp);
                d->_fmhp->setZValue(100);
            }

            if (d->_fmhp)
            {
                d->_fmhp->definitionPoint = QPointF(params.fixedPoint.x(), params.fixedPoint.y());
            }

            if (!d->_fmvp)
            {
                d->_fmvp = new VDefinitionPoint();
                d->_scene->addItem(d->_fmvp);
                d->_fmvp->setZValue(100);
            }

            if (d->_fmvp)
            {
                d->_fmvp->definitionPoint = QPointF(params.fixedPoint.x(), params.fixedPoint.y());
            }

            VDefinitionPoint* vp = new VDefinitionPoint();
            vp->definitionPoint = QPointF(-0.5 * params.materialsWidth, params.materialsThickness);
            d->_scene->addItem(vp);
            vp->setZValue(100);
            d->_vps[-999] = vp;

            HDefinitionPoint* hp;// = new HDefinitionPoint();
//             hp->definitionPoint = QPointF(-0.5 * params.materialsWidth, params.materialsThickness);
//             d->_scene->addItem(hp);
//             hp->setZValue(100);
//             d->_hps[-999] = hp;

            vp = new VDefinitionPoint();
            vp->definitionPoint = QPointF(+0.5 * params.materialsWidth, params.materialsThickness);
            d->_scene->addItem(vp);
            vp->setZValue(100);
            d->_vps[+999] = vp;

//             hp = new HDefinitionPoint();
//             hp->definitionPoint = QPointF(+0.5 * params.materialsWidth, params.materialsThickness);
//             d->_scene->addItem(hp);
//             vp->setZValue(100);
//             d->_hps[+999] = hp;

            

            int i = 0;
            for (auto dp : params.definitionPoints)
            {
                if (dp.type == 0)
                {
                    dp.type = 2;
                }
                if (dp.type & DT_FullWidth)
                {
                    if (dp.thicknessLeft > 0)
                    {
                        vp = new VDefinitionPoint();
                        vp->definitionPoint = QPointF(-dp.distance, dp.thicknessLeft);
                        d->_scene->addItem(vp);
                        vp->setZValue(100);
                        d->_vps[i] = vp;

                        hp = new HDefinitionPoint();
                        hp->definitionPoint = QPointF(-dp.distance, dp.thicknessLeft);
                        d->_scene->addItem(hp);
                        hp->setZValue(100);
                        d->_hps[i] = hp;
                        i++;
                    }
                    
                    if (dp.thicknessRight > 0)
                    {
                        vp = new VDefinitionPoint();
                        vp->definitionPoint = QPointF(+dp.distance, dp.thicknessRight);
                        d->_scene->addItem(vp);
                        vp->setZValue(100);
                        d->_vps[i] = vp;

                        hp = new HDefinitionPoint();
                        hp->definitionPoint = QPointF(+dp.distance, dp.thicknessRight);
                        d->_scene->addItem(hp);
                        hp->setZValue(100);
                        d->_hps[i] = hp;
                        i++;
                    }
                }
                else if (dp.type & DT_HalfWidth)
                {
                    if (dp.thicknessLeft > 0)
                    {
                        vp = new VDefinitionPoint();
                        vp->definitionPoint = QPointF(-dp.distance, dp.thicknessLeft);
                        d->_scene->addItem(vp);
                        vp->setZValue(100);
                        d->_vps[i] = vp;

                        hp = new HDefinitionPoint();
                        hp->definitionPoint = QPointF(-dp.distance, dp.thicknessLeft);
                        d->_scene->addItem(hp);
                        hp->setZValue(100);
                        d->_hps[i] = hp;
                        i++;

                        vp = new VDefinitionPoint();
                        vp->definitionPoint = QPointF(+dp.distance, dp.thicknessLeft);
                        d->_scene->addItem(vp);
                        vp->setZValue(100);
                        d->_vps[i] = vp;

                        hp = new HDefinitionPoint();
                        hp->definitionPoint = QPointF(+dp.distance, dp.thicknessLeft);
                        d->_scene->addItem(hp);
                        hp->setZValue(100);
                        d->_hps[i] = hp;
                        i++;
                    }
                }
                
            }
            if (params.measureThickness.size()>0)
            {
                g_VDefinitionPoint.clear();
                g_VFormualPoint.clear();
            }
            
            for (auto dp : params.measureThickness)
            {
                vp = new VDefinitionPoint();
                vp->definitionPoint = QPointF(dp.x(), dp.y());
                d->_scene->addItem(vp);
                vp->setZValue(100);
                d->_mvps.append(vp);
                g_VDefinitionPoint.append(dp.x());
                g_VFormualPoint.append(dp.x());
                hp = new HDefinitionPoint();
                hp->definitionPoint = QPointF(dp.x(), dp.y());
                d->_scene->addItem(hp);
                hp->setZValue(100);
                d->_mhps.append(hp);
            }
          
            d->updatePageFlag();

            QMetaObject::invokeMethod(this, "zoomFit", Qt::QueuedConnection);
        }

        void ToolProfilesView::setTemplate(const OiProfiles& profiles)
        {
            OI_F(ToolProfilesView);

            d->_line->_template = profiles;
        }

        void ToolProfilesView::setProfiles(const OiProfiles& profiles)
        {
            OI_F(ToolProfilesView);

            d->_line->_profiles = profiles;
        }

        void ToolProfilesView::setValues(const OiResultData& data)
        {
            OI_F(ToolProfilesView);

            if (data.contains("definitionPoints"))
            {
                QMap<int, QPointF> values = data["definitionPoints"].value<QMap<int, QPointF>>();

                for (auto iter = values.begin(); iter != values.end(); iter++)
                {
                    int index = iter.key();
                    QPointF pv = iter.value();
                    if (d->_vps.contains(index))
                    {
                        d->_vps[index]->definitionPoint = QPointF(round(pv.x() * 1e2) / 1e2, round(pv.y() * 1e2) / 1e2);
                    }

                    if (d->_hps.contains(index))
                    {
                        d->_hps[index]->definitionPoint = QPointF(round(pv.x() * 1e2) / 1e2, round(pv.y() * 1e2) / 1e2);
                    }
                }

                d->_wps->definitionPoint1 = values[TT_LeftSide];
                d->_wps->definitionPoint2 = values[TT_RightSide];
            }

            if (data.contains("measureThickness"))
            {
                QList<QPointF> values = data["measureThickness"].value<QList<QPointF>>();

                for (int i = 0; i < values.size(); i++)
                {
                    QPointF pv = QPointF(round(values[i].x() * 1e2) / 1e2, round(values[i].y() * 1e2) / 1e2);
                    if (d->_mvps.size() > i)
                    {
                        d->_mvps[i]->definitionPoint = pv;
                    }

                    if (d->_mhps.size() > i)
                    {
                        d->_mhps[i]->definitionPoint = pv;
                    }
                    if (g_VDefinitionPoint.size() > i)
                    {
                        g_VDefinitionPoint[i] = pv.x();
                    }
                }
            }
        }

        void ToolProfilesView::setResult(const WorkResult::Result& result)
        {
            OI_F(ToolProfilesView);

            OiProfiles profiles;
            profiles << result.profile;

            if (result.params != d->_params)
            {
                setParams(result.params);
            }
            setProfiles(profiles);
            setValues(result.data);

            d->_scene->update();
        }

        void ToolProfilesView::addMeasureTool()
        {
            OI_F(ToolProfilesView);

            auto py = d->y_at_x(0.0);
            py = round(py * 1e2) / 1e2;
            if (py >= 0)
            {
                d->_addToolMode = true;

                setCursor(Qt::ArrowCursor);

                VDefinitionPoint* vp = new VDefinitionPoint();
                vp->definitionPoint = QPointF(0.0, py);
                d->_scene->addItem(vp);
                vp->setZValue(100);

                d->_mvps.append(vp);

                HDefinitionPoint* hp = new HDefinitionPoint();
                hp->definitionPoint = QPointF(0.0, py);
                hp->cornerPoint = QPointF(0.0, py);
                d->_scene->addItem(hp);
                hp->setZValue(100);

                d->_mhps.append(hp);
            }
        }

        void ToolProfilesView::addMeasurePoint(QPointF point)
        {
            OI_F(ToolProfilesView);
            setCursor(Qt::ArrowCursor);

            VDefinitionPoint* vp = new VDefinitionPoint();
            vp->definitionPoint = point;
            d->_scene->addItem(vp);
            vp->setZValue(100);

            d->_mvps.append(vp);

            HDefinitionPoint* hp = new HDefinitionPoint();
            hp->definitionPoint = point;
            d->_scene->addItem(hp);
            hp->setZValue(100);

            d->_mhps.append(hp);
        }

        void ToolProfilesView::setEditable(bool enable)
        {
            OI_IMPL()->_editable = enable;
        }

        QPointF ToolProfilesView::setMeasureToolPos(int i, double x)
        {
            OI_F(ToolProfilesView);
            auto py = d->y_at_x(x);
            py = round(py * 1e2) / 1e2;

            auto pos = QPointF(x, py);

            d->_mvps[i]->definitionPoint = pos;
            d->_mhps[i]->definitionPoint = pos;

            d->relocate();

            return pos;
        }

        QPointF ToolProfilesView::setFixedMeasurePos(double x)
        {
            OI_F(ToolProfilesView);
            auto py = d->y_at_x(x);
            py = round(py * 1e2) / 1e2;

            auto pos = QPointF(x, py);

            d->_fmhp->definitionPoint = pos;
            d->_fmvp->definitionPoint = pos;

            d->relocate();

            return pos;
        }

        void ToolProfilesView::onClearView()
        {
            OI_IMPL()->clearView();
        }

        void ToolProfilesView::zoomFit()
        {
            OI_F(ToolProfilesView);

//            fitInView(d->_line, Qt::IgnoreAspectRatio);

            d->relocate();

            auto rect = d->_line->boundingRect();

            for (auto vp : d->_vps)
            {
                rect |= vp->boundingRect();
            }

            for(auto hp : d->_hps)
            {
                rect |= hp->boundingRect();
            }

            for (auto vp : d->_mvps)
            {
                rect |= vp->boundingRect();
            }

            for (auto hp : d->_mhps)
            {
                rect |= hp->boundingRect();
            }

            rect = QRectF(rect.x() - rect.width() * 0.1, rect.y() - rect.height() * 0.1, rect.width() * 1.2, rect.height() * 1.2);

            fitInView(rect, Qt::IgnoreAspectRatio);

//            d->_scene->update();

//             d->relocate();
// 
//             rect = d->_line->boundingRect();
// 
//             for(auto vp : d->_vps)
//             {
//                 rect |= vp->textRect();
//             }
// 
//             for(auto hp : d->_hps)
//             {
//                 rect |= hp->textRect();
//             }
// 
//             rect = QRectF(rect.x() - rect.width() * 0.1, rect.y() - rect.height() * 0.1, rect.width() * 1.2, rect.height() * 1.2);
// 
//             fitInView(rect, Qt::IgnoreAspectRatio);
        }

        void ToolProfilesView::mousePressEvent(QMouseEvent *event)
        {
            OI_F(ToolProfilesView);

            if(event->button() == Qt::MiddleButton)
            {
                setDragMode(QGraphicsView::ScrollHandDrag);
                QMouseEvent evt(event->type(), event->pos(), Qt::LeftButton, event->buttons(), event->modifiers());
                QGraphicsView::mousePressEvent(&evt);
                event->accept();
                return;
            }

            QGraphicsView::mousePressEvent(event);
        }

        void ToolProfilesView::mouseReleaseEvent(QMouseEvent *event)
        {
            OI_F(ToolProfilesView);

            if (event->button() & Qt::LeftButton)
            {
                if (d->_addToolMode)
                {
                    d->_addToolMode = false;
                    event->accept();

                    emit addToolComplete(d->_mhps.last()->definitionPoint);
                    d->relocate();

                    d->_scene->update();
                    return;
                }
            }
            else if (event->button() & Qt::RightButton)
            {
                if (d->_addToolMode)
                {
                    d->_addToolMode = false;

                    if (d->_mhps.size() > 0)
                    {
                        delete d->_mhps.last();
                        d->_mhps.removeLast();
                    }
                    
                    if (d->_mvps.size() > 0)
                    {
                        delete d->_mvps.last();
                        d->_mvps.removeLast();
                    }

                    event->accept();
                    return;
                }
            }
            else if(event->button() == Qt::MiddleButton)
            {
                QMouseEvent evt(event->type(), event->pos(), Qt::LeftButton, event->buttons(), event->modifiers());
                QGraphicsView::mouseReleaseEvent(&evt);
                event->accept();
                setDragMode(QGraphicsView::RubberBandDrag);
//                d->relocate();
                return;
            }

            QGraphicsView::mouseReleaseEvent(event);
        }

        void ToolProfilesView::mouseMoveEvent(QMouseEvent *event)
        {
            OI_F(ToolProfilesView);

            if (d->_addToolMode)
            {
                auto pos = mapToScene(event->pos());

                auto vp = d->_mvps.last();
                auto hp = d->_mhps.last();

                double mx = round(pos.x() * 1e2) / 1e2;
                double my = round(pos.y() * 1e2) / 1e2;
                auto py = d->y_at_x(mx);
                py = round(py * 1e2) / 1e2;
                if (py >= 0)
                {
                    vp->definitionPoint = QPointF(mx, py);
                    hp->definitionPoint = QPointF(mx, py);
                    hp->cornerPoint = QPointF(mx, my);

                    vp->change();
                    hp->change();
                }

                event->accept();

                return;
            }
            else
            {
                auto pos = mapToScene(event->pos());

                double v1 = -1.0, v2 = -1.0;
                if (d->_line->_template.size() > 0)
                {
                    v1 = PLScannerUtil::y_at_profile(d->_line->_template[0], pos.x());
                }

                if (d->_line->_profiles.size() > 0)
                {
                    v2 = PLScannerUtil::y_at_profile(d->_line->_profiles[0], pos.x());
                }

                if (v1 <= 0.0)
                {
                    d->_info->hide();
                    d->_scene->update();
                }
                else
                {
                    if (v2 > 0.0)
                    {
                        d->_info->stdValue = v1;
                        d->_info->measureValue = v2;
                        d->_info->setPos(QPointF(pos.x(), v2));

                    }
                    else
                    {
                        d->_info->stdValue = v1;
                        d->_info->measureValue = 0.0;
                        //d->_info->_referPoint = QPointF(pos.x(), v1);
                        d->_info->setPos(QPointF(pos.x(), v1));


                    }
                    d->_info->show();
                }
            }

            QGraphicsView::mouseMoveEvent(event);

//             if(dragMode() == QGraphicsView::ScrollHandDrag)
//             {
//                 d->relocate();
//             }
        }

        void ToolProfilesView::mouseDoubleClickEvent(QMouseEvent *event)
        {
            OI_F(ToolProfilesView);

            if(event->button() == Qt::MiddleButton)
            {
                zoomFit();
            }
            else if (event->button() == Qt::LeftButton)
            {
                auto epos = event->pos();
                auto spos = mapToScene(epos);

                for (auto iter = d->_hps.begin(); iter != d->_hps.end(); iter++)
                {
                    if ((*iter)->textRect().contains(spos))
                    {
                        emit toolDoubleClicked(iter.key(), 0);
                    }
                }

                for (auto iter = d->_vps.begin(); iter != d->_vps.end(); iter++)
                {
                    if ((*iter)->textRect().contains(spos))
                    {
                        emit toolDoubleClicked(iter.key(), 1);
                    }
                }

                for (int i = 0; i < d->_mhps.size(); i++)
                {
                    if (d->_mhps[i]->isVisible() && d->_mhps[i]->textRect().contains(spos))
                    {
                        emit toolDoubleClicked(TT_MeasureThicknessTool + i, 0);
                    }
                }

                for (int i = 0; i < d->_mvps.size(); i++)
                {
                    if (d->_mvps[i]->isVisible() && d->_mvps[i]->textRect().contains(spos))
                    {
                        emit toolDoubleClicked(TT_MeasureThicknessTool + i, 1);
                    }
                }

                if (d->_wps->textRect().contains(spos))
                {
                    emit toolDoubleClicked(TT_TotolWidth, 0);
                }

                if (d->_fmhp->isVisible() && d->_fmhp->textRect().contains(spos))
                {
                    emit toolDoubleClicked(TT_FixedPointMeasure, 0);
                }

                if (d->_fmvp->isVisible() && d->_fmvp->textRect().contains(spos))
                {
                    emit toolDoubleClicked(TT_FixedPointMeasure, 1);
                }
            }
        }

        void ToolProfilesView::wheelEvent(QWheelEvent *event)
        {
            OI_F(ToolProfilesView);

            if(event->delta() > 0)
            {
                if(transform().m11() < 1e+5)
                {
                    scale(1.0 * 1.15, 1.0 * 1.15);
                    d->relocate();
                }
            }
            else
            {
                if(transform().m11() > 1e-5)
                {
                    scale(1.0 / 1.15, 1.0 / 1.15);
                    d->relocate();
                }
            }
        }

        void ToolProfilesView::drawForeground(QPainter *painter, const QRectF &rect)
        {
            OI_F(ToolProfilesView);

            auto vr = viewport()->rect();
            auto tf = painter->transform();
            auto ty = mapToScene(vr.topLeft()).y();
            auto by = mapToScene(vr.bottomRight()).y();

            painter->save();
            painter->scale(1.0 / tf.m11(), 1.0 / tf.m22());
            painter->setPen(QPen(Qt::gray, 1.0, Qt::DashDotDotLine));
            painter->drawLine(QLine(QPoint(0, ty * tf.m22()), QPoint(0, by * tf.m22())));
            painter->restore();
        }

        void ToolProfilesView::contextMenuEvent(QContextMenuEvent *event)
        {
            OI_F(ToolProfilesView);

            auto epos = event->pos();
            auto spos = mapToScene(epos);

            int connectId = -1;

            for (int i = 0; i < d->_mhps.size(); i++)
            {
                if (d->_mhps[i]->textRect().contains(spos))
                {
                    connectId = i;
                    break;
                }
            }

            if (connectId < 0)
            {
                for (int i = 0; i < d->_mvps.size(); i++)
                {
                    if (d->_mvps[i]->textRect().contains(spos))
                    {
                        connectId = i;
                        break;
                    }
                }
            }

            if (connectId >= 0)
            {
                QMenu menu(this);

                QAction* action = menu.addAction(tr("删除"));
                action->setData(0);
                action->setEnabled(d->_editable);

                action = menu.exec(event->globalPos());

                if (action)
                {
                    switch (action->data().toInt())
                    {
                    case 0:
                        if (QMessageBox::Ok == QMessageBox::information(this, tr("确定删除"),
                            tr("是否删除此测量点?"), QMessageBox::Ok | QMessageBox::No, QMessageBox::No))
                        {
                            delete d->_mhps[connectId];
                            delete d->_mvps[connectId];
                            d->_mhps.removeAt(connectId);
                            d->_mvps.removeAt(connectId);
                            emit delTool(connectId);
                        }
                        break;
                    }

                }
            }
            
            
        }

        void ToolProfilesView::enterEvent(QEvent *event)
        {
        }

        void ToolProfilesView::leaveEvent(QEvent *event)
        {
            OI_F(ToolProfilesView);
            d->_info->hide();
            d->_scene->update();
        }

    }
}